home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / vgacodng / part07.txt < prev    next >
Text File  |  1996-12-15  |  13KB  |  332 lines

  1.  
  2.                              VGA-Kurs - Part #7
  3.  
  4. Hallo Leute! Es wird Zeit für 'T.C.P.'s Beginner's Guide To VGA Coding',
  5. Part VII!
  6. In den ersten 6 Teilen haben wir die Grundlagen des VGA Codings besprochen
  7. (allerdings ohne dabei auf die Register der VGA-Karte selbst einzugehen, wer
  8. dazu Informationen braucht, möge sich bitte ein Buch kaufen, ich empfehle
  9. "VGA- und SVGA-Programmierung" von M. Uphoff, Addison Wesley).
  10. Ich werde ab jetzt in den folgenden Teilen dieses Kurses diese Grundlagen als
  11. Wissen vorraussetzen und auf verschiedene Effekte, Tricks oder ähnliches
  12. eingehen.
  13. In diesem Teil will ich mit einem sehr simplen Effekt anfangen, mit dem sich
  14. allerdings sehr schöne Resultate erzielen lassen: Der Shadebob-Effekt.
  15. Die Shadebobs sind meiner Meinung nach zu Unrecht wegen ihrer einfachen
  16. Programmierung in Verruf gekommen, und werden häufig als Lamer-Effekt betitelt.
  17. Ich für meinen Teil habe nichts gegen Shadebobs in Demos, auch wenn sie schon
  18. etwas älter sind. Man kann mit dem Prinzip wirklich sehr viel anfangen, man
  19. sollte es nur nicht übertreiben, wie es manche ältere Demos zeigen, in denen
  20. zum Teil bis zu 5 Minuten lange Shadebob-Parts enthalten sind.
  21. Aber fangen wir jetzt an.
  22. Das Prinzip der Shadebobs ist einfach erklärt. Wenn man sich ein beliebiges
  23. Quadrat auf dem schwarzen Screen sucht, und alle Pixelwerte dieses Quadrates um
  24. eins erhöht, sieht man ein blaues Quadrat, weil in der Standardpalette nach der
  25. Farbe 0 (schwarz) die Farbe blau kommt. Wenn man nun ein anderes, gleichgroßes
  26. Quadrat nimmt, das sich mit dem alten in einem Pixel überlagert, dann ist dieses
  27. auch blau, nur das eine Pixel, an dem sich die beiden überlagern, hat die Farbe
  28. grün, denn sein Farbwert wurde zweimal erhöht.
  29. Falls ihr euch nicht so genau vorstellen könnt, wie das vor sich geht, hilft
  30. euch vielleicht das Listing weiter.
  31.  
  32. uses crt;
  33. var n1,n2 : byte;
  34. begin
  35.   asm mov ax,13h; int 10h end;
  36.   for n1 := 0 to 9 do
  37.     for n2 := 0 to 9 do mem[$A000:n2*320+n1] := mem[$A000:n2*320+n1] + 1;
  38.   for n1 := 9 to 18 do
  39.     for n2 := 9 to 18 do mem[$A000:n2*320+n1] := mem[$A000:n2*320+n1] + 1;
  40.   readkey;
  41.   asm mov ax,3; int 10h end;
  42. end.
  43.  
  44. Wenn wir jetzt eine Farbpalette setzen, die einen durchgehenden blauen
  45. Farbverlauf enthält, und ständig neue Quadrate an zufälligen Positionen auf den
  46. Bildschirm setzen, hätten wir den ersten Shadebob-Typ: Die Colorcycle-Bobs.
  47.  
  48. uses crt;
  49. var Pal : array[0..767] of byte;
  50.     n1,n2 : byte;
  51.  
  52. procedure SetPalette;assembler;    { Setzt die Palette in Pal }
  53. asm
  54.   mov     dx,3C8h
  55.   xor     al,al
  56.   out     dx,al
  57.   mov     cx,768
  58.   mov     dx,3C9h
  59.   mov     si,offset pal
  60. @Jmp1:
  61.   lodsb
  62.   out     dx,al
  63.   loop    @Jmp1
  64. end;
  65.  
  66. procedure BluePal;   { Schreibt eine blaue Palette in Pal setzt sie mittels }
  67. var loop : integer;  { SetPalette }
  68.  
  69. begin
  70.   for loop := 0 to 31 do begin
  71.     pal[loop*3+2] := loop * 2;
  72.     pal[(63-loop)*3+2] := loop * 2;
  73.     pal[(loop+64)*3+2] := loop * 2;
  74.     pal[(127-loop)*3+2] := loop * 2;
  75.     pal[(loop+128)*3+2] := loop * 2;
  76.     pal[(191-loop)*3+2] := loop * 2;
  77.     pal[(loop+192)*3+2] := loop * 2;
  78.     pal[(255-loop)*3+2] := loop * 2;
  79.   end;
  80.   setpalette;
  81. end;
  82.  
  83. procedure SetBob(x,y:word);  { Setzt ein Bob an die Koords X,Y }
  84. var n1,n2 : byte;
  85.  
  86. begin
  87.   for n1 := 0 to 19 do    { Hier werden in einem 20x20 Pixel großen Quadrat }
  88.     for n2 := 0 to 19 do  { alle Pixelwerte um 1 erhöht }
  89.       mem[$A000:(n2+y)*320+n1+x] := mem[$A000:(n2+y)*320+n1+x] + 1;
  90. end;
  91.  
  92. begin
  93.   asm mov ax,13h; int 10h end;
  94.   BluePal;
  95.   randomize;
  96.   repeat
  97.     SetBob(random(300),random(180)); { Bob an zufällige Position setzen }
  98.   until keypressed;
  99.   readkey;
  100.   asm mov ax,3; int 10h end;
  101. end.
  102.  
  103. Das obige Listing enthält noch eine Pascal-Version der SetBob-Routine, die
  104. nicht gerade sehr optimiert ist. Wer also gerade zu viel Zeit hat, kann das
  105. Ganze noch ein bißchen optimieren.
  106. In der dritten Zeile der SetBob-Prozedur kann das '+ 1' durch ein '+ random(4)'
  107. ersetzt werden. Dadurch wird der Effekt körniger. Ist Geschmackssache.
  108. So, das Prinzip der Shadebobs dürfte jetzt klar sein.
  109. Als zweite in der Reihe der verschiedenen Shadebob-Typen wären da die Snakebobs.
  110. Bei dieser Art von Bobs werden entweder ein oder mehrere (je mehr desto besser)
  111. Shadebobs gezeichnet und dann z.B. um ein Pixel nach rechts und eins nach unten
  112. bewegt. Das macht man solange, bis der Bob am unteren Rand des Screens angelangt
  113. hat. Man hat jetzt eine Line, die schräg über den Bildschirm verläuft. Nun
  114. ändert man die Bewegungsrichtung, indem man den Inkrementationsparameter
  115. umkehrt, also den Bob jetzt nach oben bewegt. Trifft der Bob nun auf den rechten
  116. Rand des Screens, kehrt man auch die horizontale Bewegungsrichtung um.
  117. Das sieht dann so aus:
  118.  
  119. uses crt;
  120. var Pal : array[0..767] of byte;
  121.     x1,y1,x2,y2 : word;            { X- und Y-Koords der beiden Bobs }
  122.     incx1,incy1,incx2,incy2 : shortint; { Inkrementationsparameter }
  123.  
  124. { Hier die Prozeduren SetBob und SetPalette einfügen }
  125.  
  126. procedure RainbowPal; { Erstellt eine bunte Palette }
  127. var loop : integer;
  128.  
  129. begin
  130.   for loop := 0 to 31 do begin
  131.     pal[loop*3] := loop * 2;
  132.     pal[(63-loop)*3] := loop * 2;
  133.     pal[(loop+64)*3+1] := loop * 2;
  134.     pal[(127-loop)*3+1] := loop * 2;
  135.     pal[(loop+128)*3+2] := loop * 2;
  136.     pal[(191-loop)*3+2] := loop * 2;
  137.     pal[(loop+192)*3] := loop * 2;
  138.     pal[(loop+192)*3+1] := loop * 2;
  139.     pal[(loop+192)*3+2] := loop * 2;
  140.     pal[(255-loop)*3] := loop * 2;
  141.     pal[(255-loop)*3+1] := loop * 2;
  142.     pal[(255-loop)*3+2] := loop * 2;
  143.   end;
  144.   setpalette;
  145. end;
  146.  
  147. begin
  148.   asm mov ax,13h; int 10h end;
  149.   RainbowPal;
  150.   randomize;
  151.   x1 := random(280);               { Zufällige X- und Y- Positionen für }
  152.   y1 := random(160);               { beide Bobs }
  153.   x2 := random(280);
  154.   y2 := random(160);
  155.   incx1 := 1;                      { Bob 1 wird nach rechts und nach unten }
  156.   incy1 := 1;                      { bewegt }
  157.   incx2 := -1;                     { Bob 2 wird nach links und nach unten }
  158.   incy2 := 1;                      { bewegt }
  159.   repeat
  160.     inc(x1,incx1);                 { Bob-Positionen verändern }
  161.     inc(y1,incy1);
  162.     inc(x2,incx2);
  163.     inc(y2,incy2);
  164.     if (x1 = 299) or (x1 = 0) then incx1 := -incx1; { Überprüfen, ob einer }
  165.     if (y1 = 179) or (y1 = 0) then incy1 := -incy1; { der Bobs am Rand des }
  166.     if (x2 = 299) or (x2 = 0) then incx2 := -incx2; { Screens ist, und wenn }
  167.     if (y2 = 179) or (y2 = 0) then incy2 := -incy2; { ja dann Wert umkehren }
  168.     SetBob(x1,y1);                 { Die beiden Bobs zeichnen }
  169.     SetBob(x2,y2);
  170.   until keypressed;
  171.   readkey;
  172.   asm mov ax,3; int 10h end;
  173. end.
  174.  
  175. Wir kommen nun zu meinen persönlichen Lieblingsbobs, den Sinusbobs.
  176. Der Name basiert darauf, daß hier mittels einer Sinusformel die Koordinaten
  177. für die Bobs berechnet werden, wodurch sehr schöne Formen zustande kommen.
  178. Allerdings sind die Quadratischen Bobs hier nicht geeignet, passender sind
  179. runde. Man kann stattdessen natürlich auch kleine Symbole oder Logos benutzen,
  180. das sieht nicht schlecht aus.
  181.  
  182. uses crt;
  183.  
  184. const VGA : word = $A000;
  185.       SinOfs = 40;        { Offset                     }
  186.       SinAmp = 50;        { Amplitude                  }
  187.       SinLen = 255;       { und Länge der Sinustabelle }
  188.       SprPic : array[0..15,0..15] of byte = (
  189.         (0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0),
  190.         (0,0,0,0,2,2,3,3,3,3,2,2,0,0,0,0),
  191.         (0,0,0,2,3,3,3,3,3,3,3,3,2,0,0,0),
  192.         (0,0,2,3,3,3,3,3,3,3,3,3,3,2,0,0),
  193.         (0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,0),
  194.         (0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,0),
  195.         (2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2),
  196.         (2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2),
  197.         (2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2),
  198.         (2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2),
  199.         (0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,0),
  200.         (0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,0),
  201.         (0,0,2,3,3,3,3,3,3,3,3,3,3,2,0,0),
  202.         (0,0,0,2,3,3,3,3,3,3,3,3,2,0,0,0),
  203.         (0,0,0,0,2,2,3,3,3,3,2,2,0,0,0,0),
  204.         (0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0)
  205.       );
  206.  
  207. var SinTab : array[0..SinLen] of word;
  208.     Pal : array[0..767] of byte;
  209.     X,Y,n       : integer;
  210.     I1,I2,J1,J2 : byte;
  211.  
  212. { Hier die Prozeduren SetPalette und BluePal einsetzen }
  213.  
  214. procedure CalcSinus(SinPar:byte);
  215. begin
  216.   for n := 0 to SinLen do
  217.     SinTab[n] := round(sin(n*SinPar*pi/SinLen)*SinAmp)+SinOfs;
  218. end;
  219.  
  220. procedure WaitRetrace;assembler;
  221. asm
  222.   mov     dx,3DAh
  223. @loop1:
  224.   in      al,dx
  225.   and     al,08h
  226.   jz      @loop1
  227. @loop2:
  228.   in      al,dx
  229.   and     al,08h
  230.   jz      @loop2
  231. end;
  232.  
  233. procedure SetBob(X,Y:word;W,H:byte;Sprite:pointer);assembler;
  234. asm
  235.   push    ds                       { DS sichern }
  236.   lds     si,[Sprite]              { DS:SI mit dem Spritepointer laden }
  237.   mov     es,vga                   { VGA-Segment nach ES }
  238.   cld
  239.   mov     ax,Y                     { Offset des Bobs berechnen }
  240.   shl     ax,6
  241.   mov     di,ax
  242.   shl     ax,2
  243.   add     di,ax
  244.   add     di,X
  245.   mov     bh,H
  246.   mov     cx,320
  247.   sub     cl,W
  248.   sbb     ch,0
  249. @L:
  250.   mov     bl,W
  251. @L2:
  252.   lodsb                            { Wert laden }
  253.   or      al,al                    { Wert = 0 ? }
  254.   jz      @S                       { Wenn ja, nicht erhöhen }
  255.   mov     dl,es:[di]               { Pixelwert vom VGA holen }
  256.   add     dl,al                    { Wert erhöhen }
  257.   and     dl,63
  258.   mov     es:[di],dl               { und neuen Pixelwert schreiben }
  259. @S:
  260.   inc     di                       { nächste Pixelposition }
  261.   dec     bl                       { Zähler dekrementieren }
  262.   jnz     @L2                      { wenn <> 0 dann innerer Loop }
  263.   add     di,cx                    { nächste Zeile auf VGA }
  264.   dec     bh                       { Zähler dekrementieren }
  265.   jnz     @L                       { wenn <> 0 dann äußerer Loop }
  266.   pop     ds
  267. end;
  268.  
  269. begin
  270.   asm mov ax,13h; int 10h end;
  271.   BluePal;
  272.   randomize;
  273.   CalcSinus(random(8));  { Sinustabelle berechnen }
  274.   I1 := 0;               { Indizes für Sinustabelle }
  275.   I2 := 200;
  276.   J1 := 0;
  277.   J2 := 200;
  278.   repeat
  279.     X := SinTab[I1]+SinTab[I2];  { Werte addieren }
  280.     Y := SinTab[J1]+SinTab[J2];
  281.     inc(I1,2);                   { Neue Indexwerte }
  282.     inc(I2,3);
  283.     inc(J1);
  284.     inc(J2,2);
  285.     waitretrace;
  286.     SetBob(80+X,Y,16,16,addr(SprPic)); { Bob zeichnen }
  287.   until keypressed;
  288.   readkey;
  289.   asm mov ax,3; int 10h end;
  290. end.
  291.  
  292. Das Wesentliche hier, das Berechnen der Sinustabelle, findet in der Prozedur
  293. CalcSinus statt, der ein Parameter übergeben wird, nach dem sich die spätere
  294. Form der Bobs richtet. Ebenso können die Konstanten für das Offset und die
  295. Amplitude der Tabelle am Anfang des Listings verändert werden. Wer ein bißchen
  296. Ahnung von Mathe hat, kann so zu sehr schönen Formen kommen.
  297. Die Prozedur SetBob ist in diesem Fall 100% Assembler, allerdings zeichnet sie
  298. kein Quadrat, sondern das Sprite SprPic auf den Bildschirm, wobei sie die
  299. Pixelwerte um die Werte im Sprite erhöht.
  300.  
  301. Ich hoffe, ihr könnt mit diesen schönen Effekten etwas anfangen und aus ihnen
  302. lernen. Es gibt noch eine Menge anderer Möglichkeiten, die einem die Shadebobs
  303. bieten. Man könnte sie zum Beispiel mit ein paar Vektorroutinen verbinden.
  304. Auch Delay-Vektoren wären hiermit möglich, allerdings ist es wohl sinnvoller,
  305. wenn man, anstatt alle Farbwerte des vorigen Objekts herabzusetzen, das Objekt
  306. neu in einer dunkleren Farbe zeichnet.
  307. In der nächsten Ausgabe werde ich wahrscheinlich einen anderen Effekt
  308. beschreiben. Welchen, weiß ich noch nicht genau.
  309.  
  310.  
  311.  
  312.  
  313.  
  314. [ This text copyright (c) 1995-96 Johannes Spohr. All rights reserved. ]
  315. [ Distributed exclusively through PC-Heimwerker, Verlag Thomas Eberle. ]
  316. [                                                                      ]
  317. [ No  part   of  this   document  may  be   reproduced,   transmitted, ]
  318. [ transcribed,  stored in a  retrieval system,  or translated into any ]
  319. [ human or computer language, in any form or by any means; electronic, ]
  320. [ mechanical,  magnetic,  optical,   chemical,  manual  or  otherwise, ]
  321. [ without the expressed written permission of the author.              ]
  322. [                                                                      ]
  323. [ The information  contained in this text  is believed  to be correct. ]
  324. [ The text is subject to change  without notice and does not represent ]
  325. [ a commitment on the part of the author.                              ]
  326. [ The author does not make a  warranty of any kind with regard to this ]
  327. [ material, including,  but not limited to,  the implied warranties of ]
  328. [ merchantability  and fitness  for a particular  purpose.  The author ]
  329. [ shall not be liable for errors contained herein or for incidental or ]
  330. [ consequential damages in connection with the furnishing, performance ]
  331. [ or use of this material.                                             ]
  332.